﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using CloudStorage_Backend.exception;
using CloudStorage_Backend.model;
using System.IO;
using Microsoft.AspNetCore.Hosting;

namespace CloudStorage_Backend.utils
{
    public class FileHelper
    {
        // fileChunk
        private const int maxFileSize = -1;
        public static string CleanIdentifier(string flowIdentifier)
        {
            Regex regex = new Regex("[^0-9A-Za-z_-]/g");
            return regex.Replace(flowIdentifier, "");
        }
        public static void ValidateRequest(FileChunkInfoVO info)
        {
            string flowIdentifier = CleanIdentifier(info.FlowIdentifier);

            if (info.FlowChunkNumber == 0 || info.FlowChunkSize == 0 ||
               info.FlowTotalSize == 0 || flowIdentifier.Length == 0 ||
               info.FlowFileName.Length == 0)
            {
                throw new FileChunkException(FileChunkExceptionMsg.EMPTY_UPLOAD_REQUEST);
            }

            if (info.FlowChunkNumber > info.FlowTotalChunks)
            {
                throw new FileChunkException(FileChunkExceptionMsg.CHUNK_OVERFLOW);
            }

            if (maxFileSize > 0 && info.FlowTotalSize > maxFileSize)
            {
                throw new FileChunkException(FileChunkExceptionMsg.FILE_TOO_LARGE);
            }
        }

        public static bool CheckFileChunk(FileChunkInfoVO info, int fileSize)
        {
            if (info.FlowChunkNumber < info.FlowTotalChunks && fileSize != info.FlowChunkSize)
            {
                throw new FileChunkException(FileChunkExceptionMsg.FILECHUNKSIZE_WRONG);
            }

            if (info.FlowTotalChunks > 1 && info.FlowChunkNumber == info.FlowTotalChunks
              && fileSize != ((info.FlowTotalSize % info.FlowChunkSize) + info.FlowChunkSize))
            {
                throw new FileChunkException(FileChunkExceptionMsg.LASTCHUNK_WRONG);
            }

            if (info.FlowTotalChunks == 1 && fileSize != info.FlowTotalSize)
            {
                throw new FileChunkException(FileChunkExceptionMsg.SINGLECHUNK_WRONG);
            }

            return true;
        }

        // file
        public static string ProcessPath(string input, string userName, string webRootPath)
        {
            Regex regex = new Regex(@"\.{1,2}\\");
            string path = regex.Replace(input, "");

            string root = webRootPath + $"/{userName}";
            return Path.Combine(root, path);
        }

        public static string ProcessTempPath(string identifier, int chunkNumber, string userName, string webRootPath, bool isTemp = false)
        {
            string root = webRootPath + "/TEMPORARY_FOLDER" + $"/{userName}";
            string chunkString = chunkNumber.ToString().PadLeft(5, '0');
            // 添加文件的拓展名
            string relativePath = isTemp ? $"/{identifier}/chunk-{chunkString}-downloading" : $"/{identifier}/chunk-{chunkString}-chunk";
            string tempPath = root + relativePath;
            string fullName = Directory.GetParent(tempPath).FullName;
            CreateDirs(Directory.GetParent(tempPath).FullName);
            return tempPath;
        }

        public static string ProcessFinalPath(string destinationPath, string flowRelativePath, string userName, string webRootPath)
        {
            string path = ProcessPath(destinationPath, userName, webRootPath);  // .../username/destinationpath
            Regex regex = new Regex(@"\.{1,2}\\");
            string relative = regex.Replace(flowRelativePath, "");
            if (relative.StartsWith(".."))
            {
                throw new FileException(FileExceptionMsg.WRONG_PATH_FORMAT);
            }
            string finalPath = Path.Combine(path, relative);
            CreateDirs(Directory.GetParent(finalPath).FullName);
            return finalPath;
        }

        public static void CreateDirs(string path)
        {
            if (!File.Exists(path) && !Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
        }

        public static FileInfoVO BuildDirectory(string name, string path)
        {
            return new FileInfoVO
            {
                FileName = name,
                FilePath = path,
                Size = 0,
                LastModified = DateTime.Now,
                IsDirectory = true
            };
        }

        public static void FileListCheck(string filePath)
        {
            if (File.Exists(filePath))
            {
                throw new FileException(FileExceptionMsg.INVALID_DIRECTORY_NAME);
            }
            else if (!Directory.Exists(filePath))
            {
                throw new FileException(FileExceptionMsg.DIRECTORY_NOT_FOUND);
            }
        }

        public static bool testFile(FileChunkInfoVO info, string webRootPath)
        {
            ValidateRequest(info);
            string filePathChunk = ProcessTempPath(info.FlowIdentifier, info.FlowChunkNumber, info.UserName, webRootPath);
            return File.Exists(filePathChunk);
        }

        public static bool CheckIsPicture(string fileName)
        {
            string extention = fileName.Substring(fileName.IndexOf(".")+1).ToLower();
            List<string> pictures = new List<string>()
            {
                "bmp", "tif", "tiff", "gif", "png", "jpeg", "psd", "jpg", "tga", "jfif"
            };
            if (pictures.Contains(extention))
            {
                return true;
            }
            return false;
        }
    }
}
